﻿using Microsoft.Practices.Prism.PubSubEvents;
using Microsoft.Practices.Prism.StoreApps;
using Microsoft.Practices.Prism.StoreApps.Interfaces;
using System;
using Windows.UI.Popups;
using WinRT.SIP.UILogic.Events;
using WinRT.SIP.UILogic.Repositories;

namespace WinRT.SIP.UILogic.ViewModels
{
    public class CallPageViewModel : ViewModel
    {
        private const string Incoming = "Incoming Call";
        private const string Calling = "Calling...";
        private const string Sending = "Sending...";
        private const string Connecting = "Connecting...";
        private const string InCall = "In Call";
        private const string Disconnecting = "Disconnecting...";

        private readonly ICallRepository _callRepository;
        private readonly INavigationService _navigationService;
        private readonly IEventAggregator _eventAggregator;

        private string _callStatus;
        private string _displayName;
        private bool _videoOn = true;

        public DelegateCommand AnswerCallCommand { get; private set; }
        public DelegateCommand IgnoreCallCommand { get; private set; }
        public DelegateCommand EndCallCommand { get; private set; }
        public DelegateCommand GoBackCommand { get; private set; }

        public string CallStatus
        {
            get { return _callStatus; }
            set
            {
                SetProperty(ref _callStatus, value);
                OnPropertyChanged("StreamVideo");
                OnPropertyChanged("IncomingCall");
            }
        }

        public string DisplayName
        {
            get { return _displayName; }
            set { SetProperty(ref _displayName, value); }
        }

        public bool StreamVideo
        {
            get { return CallStatus == InCall; }
        }

        public bool IncomingCall
        {
            get { return CallStatus == Incoming; }
        }

        public bool VideoOn
        {
            get { return _videoOn; }
            set
            {
                _eventAggregator.GetEvent<VideoStateChangedEvent>().Publish(value);
                SetProperty(ref _videoOn, value);
            }
        }

        public CallPageViewModel(ICallRepository callRepository, INavigationService navigationService, IEventAggregator eventAggregator)
        {
            _callRepository = callRepository;
            _navigationService = navigationService;
            _eventAggregator = eventAggregator;

            if (_callRepository.IsIncoming)
            {
                DisplayName = callRepository.GetCalleeDisplayName();
                CallStatus = Incoming;
            }
            else
            {
                MakeCall(callRepository.GetCalleeDisplayName());
            }

            GoBackCommand = new DelegateCommand(GoBack, navigationService.CanGoBack);
            AnswerCallCommand = new DelegateCommand(ConnectCall);
            IgnoreCallCommand = new DelegateCommand(() => navigationService.Navigate("Dialer", null));
            EndCallCommand = new DelegateCommand(EndCall);
        }

        private async void GoBack()
        {
            var messageDialog = new MessageDialog("Going back to the previous page will end your call already in progress.");
            messageDialog.Commands.Add(new UICommand("OK",
                new UICommandInvokedHandler((command) => EndCall())));
            messageDialog.Commands.Add(new UICommand("Cancel"));

            await messageDialog.ShowAsync();
        }

        private async void MakeCall(string phoneNumber)
        {
            CallStatus = Calling;
            DisplayName = phoneNumber;
            await _callRepository.MakeCallAsync(phoneNumber);
            ConnectCall();
        }

        private async void ConnectCall()
        {
            VideoOn = true;
            CallStatus = Connecting;
            await _callRepository.ReceiveCallAsync();
            CallStatus = InCall;
        }

        private async void EndCall()
        {
            CallStatus = Disconnecting;
            await _callRepository.EndCallAsync();

            if (VideoOn)
                VideoOn = false;
            _navigationService.GoBack();
        }
    }
}
